// database.cpp
// Customizer
// Protea Customizer / Business Logic for managing databases
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Please send correspondence to:
//
// theproteaproject@gmail.com
//

#include "customizer.h"
#include "../../../Security/base64.h"
#include "../../../Security/encrypt.h"

//
//@ CHA RevDBRelate
//@ COD RevDBRelate
//@ NUM 190
//@ CRI FORMAT_NAME (or number)
//@ TAB DB_RELATE Read 
//
//@ GEN Reviews the DB Relate records for a given format
//
TRANSACTION_CODE( RevDBRelate ) {
	XCBuffer* TransBuf = NULL;
	XCBuffer* detail = NULL;
	XCDBStatement* stmt = NULL;

	START_TXN( RevDBRelate );

		TransBuf = App->CreateBuffer( FMT_DB_RELATE, false );

		//@ Move supplied buffer information into transaction buffer
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );

		//@ Check for validation errors
		txnvars.Errors->Check();

		START_DB_TXN();
			XCSQLGen* query = txnvars.query;

			//@ UTL LookupNumberFromName to translate format name into a format number
			if (!LookupNumberFromName( &txnvars, txnvars.buffer, TransBuf, FLD_FORMAT_NUMBER, FLD_FORMAT_NAME, FMT_FORMAT_DESCRIPTR ))
				txnvars.Errors->Add( ERR_DOESNT_EXIST, SEV_ERROR, FLD_FORMAT_NAME, 1, ERR_FORMAT ); 

			txnvars.Errors->Check();

			TransBuf->DebugDump();

			App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );

			stmt = DBRelateReviewFormat( TransBuf, &txnvars );
			if (!stmt->Eof()) {
				int child = txnvars.buffer->GetChildFormat();
				if (child) {
					detail = App->CreateBuffer( child, false );

					// Send all other data packets
					while (!stmt->Eof()) {
						detail->MoveCorresponding( TransBuf, txnvars.Errors );
						txnvars.Errors->Check();

						LookupNameFromNumber( &txnvars, TransBuf, detail, FLD_FIELD_NUMBER, FLD_FIELD_NAME, FMT_FIELD_DESCRIPTOR );
						txnvars.Errors->Check();

						App->TransResponse( txnvars.result, detail, TRANS_DETAIL_TYPE );
						stmt->MoveNext();
					};
				};
			};

			//@ End the transaction
		END_DB_TXN();

		CLEANUP_TXN()
			App->CleanupObjects( 3, &TransBuf, &stmt, &detail );
	END_TXN();
};




//
//@ CHA RevDatabases
//@ COD RevDatabases
//@ NUM 190
//@ CRI APPL_NBR
//@ TAB DATABASE_DEFN Read
//
//@ GEN RevApplications will list all application records
//
TRANSACTION_CODE( RevDatabases ) {
	XCBuffer* TransBuf = NULL;
	XCBuffer* detail = NULL;
	XCDBStatement* stmt = NULL;

	XCSQLGen* query;

	//@ GRS Start the transaction
	START_TXN( RevApplications );

		//@ Create format descriptor buffer
		TransBuf = App->CreateBuffer( FMT_DATABASE_DEFN, false );

		//@ Move screen info to transaction buffer
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );
		txnvars.Errors->Check();

		START_DB_TXN();
			query = txnvars.query;

			App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );

			int child = txnvars.buffer->GetChildFormat();
			if (child) {
				detail = App->CreateBuffer( child, true );

				// Execute the query
				query->MakeSELECT( TransBuf );
				query->AddWHERE( 1, TransBuf->GetField( FLD_APPL_NBR ) );
				stmt = txnvars.dbtxn->ExecuteSQL( query );

				while (!stmt->Eof()) {
					detail->MoveCorresponding( TransBuf, txnvars.Errors, true );
					App->TransResponse( txnvars.result, detail, TRANS_DETAIL_TYPE );
					stmt->MoveNext();
				};
			};

		END_DB_TXN();

	CLEANUP_TXN();
		App->CleanupObjects( 3, &TransBuf, &detail, &stmt );
	END_TXN();
	//@ GRE End the transaction
};






//
//@ CHA AddDatabase
//@ COD AddDatabase
//@ NUM 190
//@ CRI DATABASE_NAME
//@ CRI USER
//@ CRI PASSWORD
//@ TAB DATABASE_DEFN Write
//
//@ GEN AddDatabase will create a new database definition record
//
TRANSACTION_CODE( AddDatabase ) {
	XCBuffer* TransBuf = NULL;

	//@ GRS Start the transaction
	START_TXN( AddDatabase );

		//@ Create DATABASE_DEFN buffer
		TransBuf = App->CreateBuffer( FMT_DATABASE_DEFN, false );

		//@ Move screen info to transaction buffer
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );

		TransBuf->DebugDump();

		//@ Start the database transaction
		START_DB_TXN();

			//@ SUB DatabaseDefnVerify to verify new database record
			DatabaseDefnVerify( TransBuf, VERIFY_ADD, &txnvars );
			txnvars.Errors->Check();

			//@ Now take the password and encrypt that value
			XCField* db_password = TransBuf->GetField( FLD_DB_PASSWORD );
			int resultlen;
			int inputlen = db_password->CalcStringSize();
			char* result = XCEncrypt( db_password->GetStringPtr(), inputlen+1, resultlen );

			// Now take the encrypted value, and save in base64
			XCBase64 base64;
			base64.Encode( db_password->GetOffset(), (unsigned char*)result, resultlen );
			delete [] result;

			//@ SUB DatabaseDefnAdd to add the new record
			DatabaseDefnAdd( TransBuf, &txnvars );

			//@ Output a LOG transaction
			LOG_TRANSACTION();

		END_DB_TXN();

		//@ Send back result buffer
		App->TransResponse( txnvars.result, TransBuf, TRANS_HEADER_TYPE );

	CLEANUP_TXN();
		App->CleanupObjects( 1, &TransBuf );
	END_TXN();
	//@ GRE End the transaction
};





//
//@ CHA DelDatabase
//@ COD DelDatabase
//@ NUM 190
//@ CRI DATABASE_NAME
//@ TAB DATABASE_DEFN Write
//
//@ GEN AddDatabase will create a new database definition record
//
TRANSACTION_CODE( DelDatabase ) {
	XCBuffer* TransBuf = NULL;

	//@ GRS Start the transaction
	START_TXN( DelDatabase );

		//@ Create DATABASE_DEFN buffer
		TransBuf = App->CreateBuffer( FMT_DATABASE_DEFN, false );

		//@ Move screen info to transaction buffer
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );

		TransBuf->DebugDump();

		//@ Start the database transaction
		START_DB_TXN();

			//@ SUB DatabaseDefnVerify to verify new database record
			DatabaseDefnVerify( TransBuf, VERIFY_DELETE, &txnvars );
			txnvars.Errors->Check();

			//@ SUB DatabaseDefnDelete to delete the record
			DatabaseDefnDelete( TransBuf, &txnvars );

			//@ Output a LOG transaction
			LOG_TRANSACTION();

		END_DB_TXN();

		//@ Send back result buffer
		App->TransResponse( txnvars.result, TransBuf, TRANS_HEADER_TYPE );

	CLEANUP_TXN();
		App->CleanupObjects( 1, &TransBuf );
	END_TXN();
	//@ GRE End the transaction
};
